package main

import (
	"fmt"
)

func main(){
	ChanUsageTest()
//	ChanCapacityTest()
//	SimpleSelectTest()
	fmt.Println("------------end------------")
}

//c1<-23 这种操作是不能使用fmt.Println打出的，一旦打出就会报错deadlock
func ChanUsageTest(){
	fmt.Println("----------ChanUsageTest()----------")
	c1:=make(chan(int),10)
//	fmt.Println("error:",c1<-23) //error
//	<-c1
	fmt.Println("deadlock--->",<-c1)
}
//channel是有容量限制的，如果：1，chan已满，再放入就会报deadlock错误，2，chan已空，再取值也回报deadlock错误
//所以使用select语句可以防止出现deadlock错误导致程序异常。
func ChanCapacityTest(){
	fmt.Println("----------ChanCapacityTest()----------")
	c1:=make(chan int, 2)
	fmt.Println("put 1")
	c1<-1
	fmt.Println("put 2")
	c1<-2
	fmt.Println("read to put 3")
//	c1<-3 // this cation here will make "deadlock"
	select {
		case c1<-3:
			fmt.Println("OK -- c1<3")
		default:
			fmt.Println("chan c1 is full")
	}
	fmt.Println("read chan c1",<-c1)
	fmt.Println("read chan c1",<-c1)
	select {
		case readFromChan:=<-c1:
			fmt.Println("read from c1",readFromChan)
		default:
			fmt.Println("chan c1 here is empty")
	}
}

//这个例子说明了chan的操作，一般最好用select来做，不然在“chan已满时放入”或者“chan已空时取出”都会报deadlock
func SimpleSelectTest(){
	fmt.Println("----------SimpleSelectTest()----------")
	var c1,c2,c3 chan int
	var i1,i2 int
	c1=make(chan(int))
	c2=make(chan(int))
	select {
		case i1=<-c1:
			fmt.Println("receive :",i1,"from c1")
		case c2<-i2:
			fmt.Println("send",i2,"to c2")
		case i3,ok:=(<-c3):
			if ok {
				fmt.Println("receive",i3,"from c3")
			}else{
				fmt.Println("c3 is closed")
			}
		default:
			fmt.Println("No communication!")
	}
}